package com.qs.security.filter;

import cn.hutool.core.util.StrUtil;
import com.qs.security.config.RsaKeyProperties;
import com.qs.security.domain.SysUser;
import com.qs.security.dto.Payload;
import com.qs.security.utils.JwtUtils;
import org.json.JSONObject;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 校验jwt token过滤器
 */
public class TokenVerityFilter extends BasicAuthenticationFilter {

    private RsaKeyProperties rsaKeyProperties;


    public TokenVerityFilter(AuthenticationManager authenticationManager, RsaKeyProperties rsaKeyProperties) {
        super(authenticationManager);
        this.rsaKeyProperties = rsaKeyProperties;
    }

    /**
     * 过滤请求
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String header = request.getHeader("authorization");
        if (StrUtil.isBlank(header) || !header.startsWith("Bearer")) {
            chain.doFilter(request, response);
            responseJson(response);
            return;
        }

        try {
            //获取用户认证失败，会抛出异常
            UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request, response);
        } catch (Exception e) {
            logger.error("\n解析jwtToken失败，未获取到用户认证信息，出现异常：", e);
            responseJson(response);
        }
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader("authorization");
        if (StrUtil.isBlank(token)) {
            logger.error("\ntoken为空");
            throw new RuntimeException("获取到的token为空");
        }

        Payload<SysUser> payload = JwtUtils.getInfoFromToken(token.replace("Bearer", ""),
                rsaKeyProperties.getPublicKey(), SysUser.class);
        SysUser sysUser = payload.getUserInfo();
        if (sysUser == null) {
            logger.error("\ntoken解析失败");
            throw new RuntimeException("token解析失败");
        }

        return new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getRoles());
    }

    private void responseJson(HttpServletResponse response) {
        try {
            PrintWriter writer = response.getWriter();
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", HttpServletResponse.SC_FORBIDDEN);
            jsonObject.put("message", "请登录");
            writer.write(jsonObject.toString());
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
